/*
 * NameGenerator.java
 *
 * Created on 12 June 2007, 19:15
 *
 * Copyright (C)
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place, Suite 330, Boston, MA 02111-1307 USA
 */

package com.grubby.generators;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Returns random surnames, based on a realistic distribution of surnames which
 * are obtained from a weighted source file containing names.
 * <P>
 * Names sourced from http://www.wardjc.com/surnames.htm.
 * <P>
 * NOTE: This class is largely based on original code created by Rob Newsome.
 * It is reused with his permission.
 *
 * @author A. HARMEL-LAW. E: andrew.harmel.law@gmail.com
 * @author Rob Newsome
 * @version 0.1
 */
public class NameGenerator {
    
    public static final Logger LOGGER
            = Logger.getLogger("com.grubby.generators.NameGenerator");
    
    /** The list of surnames read in from the provided source file */
    private List<String> surnames = new ArrayList<String>();
    
    /** Log Strings */
    private static final String NULL_PARAMETER_EX = "A parameter was null: ";
    
    /**
     * Creates a new instance of NameGenerator.
     * @param nameFileLoc The path to the file which contains your surnames;
     * each on a newline.
     */
    public NameGenerator(String nameFileLoc) {
        
        readInNames(nameFileLoc);
        
    }
    
    /**
     * Returns a random name from the generated list.
     * <P>
     * The Random object used will be seeded based on the current system time.
     * @return One of the names, randomly chosen from the list
     */
    public String nextRandomSurname() {
        
        Random rand = new Random(System.currentTimeMillis());
        return this.nextRandomSurname(rand);
        
    }
    
    /**
     * Returns a random name from the generated list.
     * <P>
     * Nullsafe - if the Random object is NULL then a IllegalArgumentException
     * will be thrown.
     * @param rand The seeded Random to use to select the random name.
     * @return One of the names, randomly chosen from the list.
     * @throws IllegalArgumentException If the Random object provided is NULL.
     */
    public String nextRandomSurname(Random rand) {
        
        String myName;
        
        if (rand == null) {
            
            LOGGER.log(Level.WARNING, NULL_PARAMETER_EX + "rand");
            throw new IllegalArgumentException(NULL_PARAMETER_EX + "rand");
            
        } else {
            
            myName = surnames.get(rand.nextInt(surnames.size()));
            
        }
        
        return myName;
    }
    
    /**
     * Reads in the names from the file at the location provided and stores
     * them in the surnames array.
     * @param surnameFileLoc the location of the file with the surnames, one
     * per line.
     * @throws IllegalArgumentException If the String object provided is NULL.
     * @throws RuntimeException If there is an IOException when interacting with
     * the file.
     */
    private void readInNames(String surnameFileLoc) {
        
        if (surnameFileLoc == null) {
            
            LOGGER.log(Level.WARNING, NULL_PARAMETER_EX
                    + "surnameFileLoc");
            throw new IllegalArgumentException(NULL_PARAMETER_EX
                    + "surnameFileLoc");
            
        }

        BufferedReader reader = null;
        
        try {
            
            reader = new BufferedReader(new FileReader(surnameFileLoc));
            
            while (reader.ready()) {
                surnames.add(reader.readLine());
            }
            
        } catch (FileNotFoundException e) {
            
            LOGGER.log(Level.WARNING, "The surname file was not found. " 
                    + "Throwing a Runtime Exception.");
            throw new RuntimeException("The surname file was not found: " 
                    + surnameFileLoc, e);
            
        } catch (IOException e) {
            
            LOGGER.log(Level.WARNING, "There was an error reading in the "
                    + "surname file.  Throwing a Runtime Exception.");
            throw new RuntimeException("Unable to read in surnames from the "
                    + "file: " + surnameFileLoc, e);
            
        } finally {
            
            try {
                
                reader.close();
                
            } catch (IOException ex) {
                
                LOGGER.log(Level.WARNING, "There was an error closing the file "
                        + "reader.  Throwing a Runtime Exception.");
                throw new RuntimeException("Error closing file reader.", ex);
                
            }
            
        }
        
    }
    
}